package org.tinygroup.jdbctemplatedslsession.template;

import java.io.Serializable;
import java.util.List;

import org.tinygroup.commons.tools.CollectionUtil;
import org.tinygroup.jdbctemplatedslsession.callback.DeleteGenerateCallback;
import org.tinygroup.jdbctemplatedslsession.callback.InsertGenerateCallback;
import org.tinygroup.jdbctemplatedslsession.callback.NoParamDeleteGenerateCallback;
import org.tinygroup.jdbctemplatedslsession.callback.NoParamInsertGenerateCallback;
import org.tinygroup.jdbctemplatedslsession.callback.NoParamUpdateGenerateCallback;
import org.tinygroup.jdbctemplatedslsession.callback.SelectGenerateCallback;
import org.tinygroup.jdbctemplatedslsession.callback.UpdateGenerateCallback;
import org.tinygroup.tinysqldsl.Delete;
import org.tinygroup.tinysqldsl.DslSession;
import org.tinygroup.tinysqldsl.Insert;
import org.tinygroup.tinysqldsl.Pager;
import org.tinygroup.tinysqldsl.Select;
import org.tinygroup.tinysqldsl.Update;

/**
 * dsl模板实现类
 * @author renhui
 *
 */
public class DslTemplateImpl extends DslAccessor implements DslTemplate{
	
	public DslTemplateImpl() {
		super();
	}
	
	public DslTemplateImpl(DslSession dslSession) {
		setDslSession(dslSession);
		afterPropertiesSet();
	}

	public <T> T insert(T t, InsertGenerateCallback<T> callback) {
		Insert insert=callback.generate(t);
		dslSession.execute(insert);
		return t; 
	}
	
	@SuppressWarnings("unchecked")
	public <T> T insertAndReturnKey(T t,
			InsertGenerateCallback<T> callback) {
		Insert insert=callback.generate(t);
		boolean autoGeneratedKeys=insert.getContext().getTable().isAutoGeneratedKeys();
		return (T) dslSession.executeAndReturnObject(insert, t.getClass(), autoGeneratedKeys);
	}

	@SuppressWarnings("unchecked")
	public <T> T insertAndReturnKey(boolean autoGeneratedKeys, T t,
			InsertGenerateCallback<T> callback) {
		Insert insert=callback.generate(t);
		return (T) dslSession.executeAndReturnObject(insert, t.getClass(), autoGeneratedKeys);
	}

	public <T> int update(T t, UpdateGenerateCallback<T> callback, boolean ignore) {
		Update update=callback.generate(t);
		return dslSession.execute(update,ignore);
	}
	
	public <T> int update(T t, UpdateGenerateCallback<T> callback) {
		return update(t, callback, true);
	}

	public int deleteByKey(Serializable pk, DeleteGenerateCallback<Serializable> callback) {
		Delete delete=callback.generate(pk);
		return dslSession.execute(delete);
	}

	@SuppressWarnings("rawtypes")
	public <T> T getByKey(Serializable pk, Class<T> requiredType,SelectGenerateCallback<Serializable> callback) {
		Select select=callback.generate(pk);
		return dslSession.fetchOneResult(select, requiredType);
	}

	public int deleteByKeys(DeleteGenerateCallback<Serializable[]> callback,
			Serializable... pks) {
		Delete delete=callback.generate(pks);
		return dslSession.execute(delete);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public <T> List<T> query(T t, SelectGenerateCallback<T> callback) {
		Select select=callback.generate(t);
		Class<T> requiredType=(Class<T>) t.getClass();
		return  dslSession.fetchList(select,requiredType);
	}

	@SuppressWarnings({"rawtypes" })
	public <T> Pager<T> queryPager(int start, int limit, T t,boolean isCursor,
			SelectGenerateCallback<T> callback) {
		Select select=callback.generate(t);
		Class<T> requiredType = requiredType(t);
		return dslSession.fetchPage(select, start, limit, false, requiredType);
	}
	
	@SuppressWarnings("unchecked")
	private <T> Class<T> requiredType(T t) {
		Class<T> requiredType=(Class<T>) t.getClass();
		return requiredType;
	}

	public <T> int[] batchInsert(List<T> objs, NoParamInsertGenerateCallback callback) {
		if (CollectionUtil.isEmpty(objs)) {
			return new int[0];
		}
		Insert insert=callback.generate();
		boolean autoGeneratedKeys=insert.getContext().getTable().isAutoGeneratedKeys();
		Class<T> requiredType = requiredType(objs.get(0));
		return dslSession.batchInsert(insert, requiredType, objs, Integer.MAX_VALUE,autoGeneratedKeys);
	}

	public <T> int[] batchInsert(boolean autoGeneratedKeys, List<T> objs,
			NoParamInsertGenerateCallback callback) {
		if (CollectionUtil.isEmpty(objs)) {
			return new int[0];
		}
		Insert insert=callback.generate();
		Class<T> requiredType = requiredType(objs.get(0));
		return dslSession.batchInsert(insert, requiredType, objs, Integer.MAX_VALUE,autoGeneratedKeys);
	}

	public <T> int[] batchUpdate(List<T> objs, NoParamUpdateGenerateCallback callback) {
		if (CollectionUtil.isEmpty(objs)) {
			return new int[0];
		}
		Update update=callback.generate();
		Class<T> requiredType = requiredType(objs.get(0));
		return dslSession.batchUpdate(update, requiredType, objs);
	}

	public <T> int[] batchDelete(List<T> objs, NoParamDeleteGenerateCallback callback) {
		if (CollectionUtil.isEmpty(objs)) {
			return new int[0];
		}
		Delete delete=callback.generate();
		Class<T> requiredType = requiredType(objs.get(0));
		return dslSession.batchDelete(delete, requiredType, objs);
	}

}
